home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Written by: Mark Krueger
-
- Copyright: © 1992 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #include <Memory.h>
- #include <Resources.h>
- #include <QuickDraw.h>
- #include <QDOffscreen.h>
- #include <OSUtils.h>
- #include <Errors.h>
- #include <FixMath.h>
-
- #include "ImageCodec.h"
-
- #include "DrawTextCodec.h"
-
- extern long
- Decompress(char *baseAddr,short rowBytes,short bwidth,short bheight,
- char *dataPtr);
-
- extern long
- Compress(char *baseAddr,short rowBytes,char *pBaseAddr,short pRowBytes,
- short width,short height,long spatialQ,long temporalQ,char *dataPtr,
- Fixed *similarityP,SharedGlobals *glob);
-
-
-
-
- /*
- Our data structure declarations
- */
-
-
-
-
-
-
- /* Function prototypes to keep the compiler smiling. */
-
- pascal ComponentResult
- DRAWTEXTCODEC(ComponentParameters *params,char **storage);
-
- pascal ComponentResult
- OpenCodec(ComponentInstance self);
-
- pascal ComponentResult
- CloseCodec(Handle storage,ComponentInstance self);
-
- pascal ComponentResult
- CanDoSelector(short selector);
-
- pascal ComponentResult
- GetVersion();
-
- pascal void
- CompressStrip(char *data,char *baseAddr,short rowBytes,short w,SharedGlobals *sg);
-
- pascal void
- DecompressStrip(char *data,char *baseAddr,short rowBytes,short w,SharedGlobals *sg);
-
-
-
- /************************************************************************************
- * This is the main dispatcher for our codec. All calls from the codec manager
- * will come through here, with a unique selector and corresponding parameter block.
- *
- * This routine must be first in the code segment of the codec thing.
- */
-
- pascal ComponentResult
- DRAWTEXTCODEC(ComponentParameters *params,char **storage)
- {
- /* If the selector is less than zero, it's a Component manager selector. */
-
- if ( params->what < 0 ) {
- switch ( params->what ) {
- case kComponentOpenSelect:
- return CallComponentFunction(params, (ComponentFunction) OpenCodec );
-
- case kComponentCloseSelect:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction) CloseCodec );
-
- case kComponentCanDoSelect:
- return CallComponentFunction(params, (ComponentFunction) CanDoSelector);
-
- case kComponentVersionSelect :
- return CallComponentFunction(params, (ComponentFunction) GetVersion);
-
- default :
- return (paramErr);
- }
- }
-
- /*
- * Here we dispatch the rest of our calls. We use the magic thing manager routine which
- * calls our subroutines with the proper parameters. The prototypes are in Image Codec.h.
- */
-
- switch ( params->what ) {
- case codecPreCompress:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDPreCompress);
-
- case codecBandCompress:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDBandCompress);
-
- case codecPreDecompress:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDPreDecompress);
-
- case codecBandDecompress:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDBandDecompress);
-
- case codecCDSequenceBusy:
- return 0; /* our codec is never asynchronously busy */
-
- case codecGetCodecInfo:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDGetCodecInfo);
-
- case codecGetCompressedImageSize:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDGetCompressedImageSize);
-
- case codecGetMaxCompressionSize:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDGetMaxCompressionSize);
-
- case codecGetCompressionTime:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDGetCompressionTime);
-
- case codecGetSimilarity:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDGetSimilarity);
-
- case codecTrimImage:
- return CallComponentFunctionWithStorage(storage,params,(ComponentFunction)CDTrimImage);
-
- default:
- return(paramErr);
- }
- }
-
-
- /************************************************************************************
- * This gets called when the thing instance is opened. We allocate our shared storage at this
- * point.
-
- * If we have shared globals, we check if they exist, otherwise we allocate
- * them and set the ComponentRefCon so that other instances can use them.
- *
- * The shared globals hold our CodecInfo struct, which we read from our resource file,
- * and some tables that we use for speed. If we cant get the tables we can work without
- * them. All items in the shared globals are made purgeable when the last of our
- * instances is closed. If our component was loaded in the application heap ( because
- * there was no room in the system heap) then we keep our shared storage in the app heap.
- *
- * We keep a pointer to the shared globals in our instance globals so that other calls can get to them.
- */
-
-
- ComponentResult
- InitSharedTables(Globals **glob,ComponentInstance self)
- {
- SharedGlobals *sGlob;
- long i,j,*lp;
- char *cp;
- short resFile;
- THz saveZone;
- Boolean inAppHeap;
- OSErr result = noErr;
-
-
- saveZone = GetZone();
- inAppHeap = ( GetComponentInstanceA5(self) != 0 );
- if ( !inAppHeap )
- SetZone(SystemZone());
- if ( (sGlob=(SharedGlobals*)GetComponentRefcon((Component)self)) == nil ) {
- if ( (sGlob = (SharedGlobals*)NewPtrClear(sizeof(SharedGlobals))) == nil ) {
- result = MemError();
- goto obail;
- }
- SetComponentRefcon((Component)self,(long)sGlob);
- }
-
- (*glob)->sharedGlob = sGlob; // keep this around where it's easy to get at
-
-
- if ( sGlob->info == nil || *(Handle)sGlob->info == nil ) {
- if ( sGlob->info )
- DisposHandle((Handle)sGlob->info);
-
- /* Get the CodecInfo struct which we keep in our resource fork */
-
- resFile = OpenComponentResFile((Component)self);
- #ifndef THINK_C // if running linked this will return an error since the res file is already open
- if ( (result=ResError() ) != 0 )
- goto obail;
- #endif THINK_C
- sGlob->info = (CodecInfo **) GetResource(codecInfoResourceType,128);
- if ( sGlob->info == nil ) {
- CloseComponentResFile(resFile);
- result = ResError();
- goto obail;
- }
- LoadResource((Handle)sGlob->info);
- if ( ResError() ) {
- sGlob->info = nil;
- CloseComponentResFile(resFile);
- result = ResError();
- goto obail;
- }
- DetachResource((Handle)sGlob->info);
- CloseComponentResFile(resFile);
- }
- HNoPurge((Handle)sGlob->info);
-
- obail:
-
- SetZone(saveZone);
- if ( result != noErr && sGlob != nil ) {
- if ( sGlob->info )
- DisposHandle((Handle)sGlob->info);
- DisposPtr((Ptr)sGlob);
- SetComponentRefcon((Component)self,(long)nil);
- }
- return(result);
- }
-
- /************************************************************************************
- * This gets called when the thing instance is opened. We allocate our storage at this
- * point. If we have shared globals, we check if they exist, and put a pointer to them
- * in our instance globals so that other calls can get to them.
- */
-
- pascal ComponentResult
- OpenCodec(ComponentInstance self)
- {
- ComponentResult result;
- Globals **glob;
- ComponentDescription ci;
-
- /*
- First we allocate shared storage. This should be a handle to any
- kind of data used by the thing instance. They should be allocated
- in the current heap.
-
- */
-
- if ( (glob = (Globals **)NewHandleClear(sizeof(Globals))) == nil ) {
- return(MemError());
- }
- SetComponentInstanceStorage(self,(Handle)glob);
-
- /* Check and initialize our shared globals */
-
- (*glob)->self = self;
- result = InitSharedTables(glob,self);
-
-
- return result;
- }
-
-
- /************************************************************************************
- * This gets called when the thing instance is closed. We need to get rid of any
- * instance storage here.
- */
-
- pascal ComponentResult
- CloseCodec(Handle storage,ComponentInstance self)
- {
- SharedGlobals *sGlob;
- long i;
- Globals **glob = (Globals **)storage;
-
- /* If we are closing our last instance
- then we make the shared global items purgeable to
- speed things up next instance.
- */
-
- if ( CountComponentInstances((Component)self) == 1) {
- if ( (sGlob=(SharedGlobals*)(*glob)->sharedGlob) != nil ) {
- if ( sGlob->info )
- HPurge((Handle)sGlob->info);
- if ( sGlob->tableWorld ) {
- DisposeGWorld(sGlob->tableWorld );
- sGlob->tableWorld = nil;
- }
- }
- }
- if ( glob ) {
- DisposHandle((Handle)glob);
- }
- return(noErr);
- }
-
-
-
- /************************************************************************************
- * Return true if we can handle the selector, otherwise false.
- */
-
- pascal ComponentResult
- CanDoSelector(short selector)
- {
- switch(selector) {
- case kComponentOpenSelect:
- case kComponentCloseSelect:
- case kComponentCanDoSelect:
- case kComponentVersionSelect :
- case codecPreCompress:
- case codecBandCompress:
- case codecPreDecompress:
- case codecBandDecompress:
- case codecCDSequenceBusy:
- case codecGetCodecInfo:
- case codecGetCompressedImageSize:
- case codecGetMaxCompressionSize:
- case codecGetCompressionTime:
- case codecGetSimilarity:
- case codecTrimImage:
- return(true);
- default:
- return (false);
- }
- }
-
-
- /************************************************************************************
- * Return the version of this component ( defines interface ) and revision level
- * of the code.
- */
-
- pascal ComponentResult
- GetVersion()
- {
- return ((1<<16) | 1); /* interface version in hi word, code rev in lo word */
- }
-
-
- /************************************************************************************
- * CDPreCompress gets called before an image is compressed, or whenever the source pixmap
- * pixel size changes when compressing a sequence. We return information about
- * how we can compress the image to the codec manager, so that it can fit the source data
- * to our requirements. The ImageDescriptor is already filled in, so we can use it for
- * reference (or even add to it ). PixelSize is the pixel depth of the source pixmap, we
- * use this as a reference for deciding what we can do. The other parameters return information
- * to the CodecManager about what we can do. We can also do setup here if we want to.
- */
-
- pascal long
- CDPreCompress(Handle storage,register CodecCompressParams *p)
- {
- Globals **glob = (Globals **)storage;
- CodecCapabilities *capabilities = p->capabilities;
-
- /*
- * First we return which depth input pixels we can deal with - based on what the
- * app has available - we can only work with 32 bit input pixels.
- */
-
- switch ( (*p->imageDescription)->depth ) {
- case 1:
- capabilities->wantedPixelSize = 1;
- break;
- default:
- return(codecConditionErr);
- break;
- }
-
- /* if the buffer gets banded, return the smallest one we can deal with */
-
- capabilities->bandMin = FONT_HEIGHT;
-
- /* if the buffer gets banded, return the increment it be should grown */
-
- capabilities->bandInc = FONT_HEIGHT;
-
-
- /*
- * If a codec needs the dimensions of the source pixmap to be of certain multiples
- * it can ask for the image to be extended out (via pixel replication) vertically
- * and/or horizontally.
- */
-
- if ( (*p->imageDescription)->width % FONT_WIDTH )
- capabilities->extendWidth = FONT_WIDTH & (FONT_WIDTH - ((*p->imageDescription)->width % FONT_WIDTH));
- if ( (*p->imageDescription)->height % FONT_HEIGHT )
- capabilities->extendHeight = FONT_HEIGHT & (FONT_HEIGHT - ((*p->imageDescription)->height % FONT_HEIGHT));
-
- if ( (*glob)->sharedGlob->tableWorld == nil )
- InitCharTab((*glob)->sharedGlob,(*glob)->self);
-
- return(noErr);
- }
-
-
- /************************************************************************************
- * CDBandCompress gets called when the codec manager wants us to compress an image, or a horizontal
- * band of an image. The pixel data at sBaseAddr is guaranteed to conform to the criteria we
- * demanded in BeginCompress.
- */
-
- pascal long
- CDBandCompress(Handle storage,register CodecCompressParams *p)
- {
- short width,height;
- Ptr cDataPtr,dataStart;
- short depth;
- Rect sRect;
- long offsetH,offsetV;
- Globals **glob = (Globals **)storage;
- register char *baseAddr;
- long numLines,numStrips;
- short rowBytes;
- char mmuMode = 1;
- register short y;
- ImageDescription **desc = p->imageDescription;
- OSErr result = noErr;
- Fixed simil;
- long csize;
- CodecQ spatialQ,temporalQ;
-
-
-
- /* If there is a progress proc, give it an open call at the start of this band. */
-
- if (p->progressProcRecord.progressProc)
- p->progressProcRecord.progressProc(codecProgressOpen,0,
- p->progressProcRecord.progressRefCon);
-
- width = (*desc)->width;
- height = (*desc)->height;
- depth = (*desc)->depth;
- dataStart = cDataPtr = p->data;
- spatialQ = p->spatialQuality;
- temporalQ = p->temporalQuality;
-
- /* figure out offset to first pixel in baseAddr from the pixelsize and bounds */
-
- rowBytes = p->srcPixMap.rowBytes & 0x3fff;
- sRect = p->srcPixMap.bounds;
- numLines = p->stopLine - p->startLine; /* number of scanlines in this band */
- numStrips = numLines/FONT_HEIGHT; /* number of strips in this band */
-
- /* adjust the source baseAddress to be at the beginning of the desired rect */
-
- switch ( p->srcPixMap.pixelSize ) {
- case 1:
- offsetH = sRect.left>>3; /* 8 pixels = 1 byte */
- break;
- default:
- result = codecErr;
- goto bail;
- }
- offsetV = sRect.top * rowBytes;
- baseAddr = p->srcPixMap.baseAddr + offsetH + offsetV;
-
-
- if ( p->conditionFlags & codecConditionFirstBand) {
- (*glob)->totalSize = 0;
- }
- else {
- /* if there is not a flush proc, adjust the pointer to the next band */
-
- if ( p->flushProcRecord.flushProc == nil )
- cDataPtr += (*glob)->totalSize;
- }
-
- /* do the slower flush/progress case if we have too */
-
- if ( p->flushProcRecord.flushProc || p->progressProcRecord.progressProc ) {
- SharedGlobals *sg = (*glob)->sharedGlob;
-
-
- for ( y=0; y < numStrips; y++) {
- SwapMMUMode(&mmuMode);
- csize = Compress(baseAddr,rowBytes,nil,0,width/FONT_WIDTH,1,spatialQ,temporalQ,
- cDataPtr,&simil,sg);
- SwapMMUMode(&mmuMode);
- baseAddr += rowBytes*FONT_HEIGHT;
- if ( p->flushProcRecord.flushProc ) {
- if ( (result=p->flushProcRecord.flushProc(cDataPtr,csize,
- p->flushProcRecord.flushRefCon)) != noErr) {
- result = codecSpoolErr;
- goto bail;
- }
- } else {
- cDataPtr += csize;
- }
- (*glob)->totalSize += csize;
- if (p->progressProcRecord.progressProc) {
- if ( (result=p->progressProcRecord.progressProc(codecProgressUpdatePercent,
- FixDiv(y,numStrips),p->progressProcRecord.progressRefCon)) != noErr ) {
- result = codecAbortErr;
- goto bail;
- }
- }
- }
- } else
- {
- SharedGlobals *sg = (*glob)->sharedGlob;
-
- SwapMMUMode(&mmuMode);
- csize = Compress(baseAddr,rowBytes,nil,0,width/FONT_WIDTH,numStrips,spatialQ,
- temporalQ,cDataPtr,&simil,sg);
- SwapMMUMode(&mmuMode);
- cDataPtr += csize;
- (*glob)->totalSize += csize;
- }
-
- /*
-
- return size and similarity on the last band
-
- */
-
- if ( p->conditionFlags & codecConditionLastBand ) {
- (*p->imageDescription)->dataSize = (*glob)->totalSize; /* return the actual size of the compressed data */
- p->similarity = 0; /* we don't do frame differencing */
- }
-
- bail:
- /* If there is a progress proc, give it a close call at the end of this band. */
-
- if (p->progressProcRecord.progressProc)
- p->progressProcRecord.progressProc(codecProgressClose,0,
- p->progressProcRecord.progressRefCon);
-
- return(result);
- }
-
-
-
- /************************************************************************************
- * CDPreDecompress gets called before an image is decompressed. We return information about
- * how we can decompress the image to the codec manager, so that it can fit the destination data
- * to our requirements.
- */
-
- pascal long
- CDPreDecompress(Handle storage,register CodecDecompressParams *p)
- {
- register CodecCapabilities *capabilities = p->capabilities;
- Rect dRect = p->srcRect;
-
- /* Check if the matrix is okay for us. We don't do anything fancy. */
-
- if ( !TransformRect(p->matrix,&dRect,nil) )
- return(codecConditionErr);
-
-
- /* Decide which depth compressed data we can deal with. */
-
- switch ( (*p->imageDescription)->depth ) {
- case 1:
- break;
- default:
- return(codecConditionErr);
- break;
- }
-
- /* We can deal only 1 bit pixels. */
-
- capabilities->wantedPixelSize = 1;
-
- capabilities->bandMin = FONT_HEIGHT;
-
- capabilities->bandInc = FONT_HEIGHT;
-
- /* If we needed our pixels to be aligned on some integer multiple we would set these to
- * the number of pixels we need the dest extended by. If we dont care, or we take care of
- * it ourselves we set them to zero.
- */
-
- if ( (*p->imageDescription)->width % FONT_WIDTH )
- capabilities->extendWidth = FONT_WIDTH & (FONT_WIDTH - ((*p->imageDescription)->width % FONT_WIDTH));
- if ( (*p->imageDescription)->height % FONT_HEIGHT )
- capabilities->extendHeight = FONT_HEIGHT & (FONT_HEIGHT - ((*p->imageDescription)->height % FONT_HEIGHT));
-
- return(noErr);
- }
-
-
- /************************************************************************************
- * CDBandDecompress gets called when the codec manager wants us to decompress an image or a horizontal
- * band of an image. The pixel data at baseAddr is guaranteed to conform to the criteria we
- * demanded in BeginDecompress. If maskIn is true, then the mask data at mBaseAddr is valid, and
- * we need to clear bits in it that correspond to any pixels in the destination we do not want to
- * change. ( We always write all pixels, so we dont care. This mode is important only for those
- * codecs that have frame differencing and don't always write all the pixels. )
- */
-
- pascal long
- CDBandDecompress(Handle storage,register CodecDecompressParams *p)
- {
- Rect dRect;
- long offsetH,offsetV;
- Globals **glob = (Globals **)storage;
- long numLines,numStrips;
- short rowBytes;
- long stripBytes;
- short width;
- register short y;
- register char *baseAddr;
- char *cDataPtr;
- char mmuMode = 1;
- OSErr result = noErr;
- long csize;
-
- /* Calculate the real base address based on the bounds rect. If it's not
- a linear transformation, we dont do it. */
-
- dRect = p->srcRect;
- if ( !TransformRect(p->matrix,&dRect,nil) )
- return(paramErr);
-
- /* If there is a progress proc, give it an open call at the start of this band. */
-
- if (p->progressProcRecord.progressProc)
- p->progressProcRecord.progressProc(codecProgressOpen,0,
- p->progressProcRecord.progressRefCon);
-
-
- /* initialize some local variables */
-
- width = (*p->imageDescription)->width;
- rowBytes = p->dstPixMap.rowBytes;
- numLines = p->stopLine - p->startLine; /* number of scanlines in this band */
- numStrips = numLines/FONT_HEIGHT; /* number of strips in this band */
- stripBytes = (width + (FONT_WIDTH-1))/FONT_WIDTH; /* number of bytes in one strip of blocks */
- cDataPtr = p->data;
-
- /* adjust the destination baseaddress to be at the beginning of the desired rect */
-
- offsetH = (dRect.left - p->dstPixMap.bounds.left);
- switch ( p->dstPixMap.pixelSize ) {
- case 1:
- offsetH >>= 3; /* 8 pixel = 1 bytes */
- break;
- default:
- result = codecErr; /* we dont handle these cases, thow we could */
- goto bail;
- }
- offsetV = (dRect.top - p->dstPixMap.bounds.top) * rowBytes;
- baseAddr = p->dstPixMap.baseAddr + offsetH + offsetV;
-
-
- /*
- * If we are skipping some data, we just skip it here. We can tell because
- * firstBandInFrame says this is the first band for a new frame, and
- * if startLine is not zero, then that many lines were clipped out.
- */
-
- if ( (p->conditionFlags & codecConditionFirstBand) ) {
- cDataPtr += p->startLine * stripBytes;
- }
-
- /*
- * If theres a dataproc spooling the data to us, then we have to do the data
- * in whatever size chunks they want to give us, or if there is a progressProc
- * make sure to call it as we go along.
- */
-
-
- if ( p->dataProcRecord.dataProc || p->progressProcRecord.progressProc ) {
- SharedGlobals *sg = (*glob)->sharedGlob;
-
- for (y=0; y < numStrips; y++) {
- if (p->dataProcRecord.dataProc) {
- if ( (result=p->dataProcRecord.dataProc(&cDataPtr,stripBytes,
- p->dataProcRecord.dataRefCon)) != noErr ) {
- result = codecSpoolErr;
- goto bail;
- }
- }
- SwapMMUMode(&mmuMode);
- csize = Decompress(baseAddr,rowBytes,width/FONT_WIDTH,1,cDataPtr);
- SwapMMUMode(&mmuMode);
- baseAddr += rowBytes*FONT_HEIGHT;
- cDataPtr += csize;
- if (p->progressProcRecord.progressProc) {
- if ( (result=p->progressProcRecord.progressProc(codecProgressUpdatePercent,
- FixDiv(y, numStrips),p->progressProcRecord.progressRefCon)) != noErr ) {
- result = codecAbortErr;
- goto bail;
- }
- }
- }
-
-
- /*
- *
- * otherwise - do the fast case.
- *
- */
-
- } else
- {
-
- SwapMMUMode(&mmuMode);
- csize = Decompress(baseAddr,rowBytes,width/FONT_WIDTH,numStrips,cDataPtr);
- SwapMMUMode(&mmuMode);
- cDataPtr += csize;
- }
-
- /*
- *
- * IMPORTANT: update pointer to data in params, so when we get the next
- * band we'll be at the right place in our data.
- *
- */
-
- p->data = cDataPtr;
-
- if ( p->conditionFlags & codecConditionLastBand ) {
- /* Tie up any loose ends on the last band of the frame, if we had any */
- }
-
- bail:
- /* If there is a progress proc, give it a close call at the end of this band. */
-
- if (p->progressProcRecord.progressProc)
- p->progressProcRecord.progressProc(codecProgressClose,0,
- p->progressProcRecord.progressRefCon);
- return(result);
- }
-
-
- /************************************************************************************
- * CDGetCodecInfo allows us to return information about ourselves to the codec manager.
- *
- * There will be a tool for determining appropriate values for the accuracy, speed
- * and level information. For now we estimate with scientific wild guessing.
- *
- * The info is stored as a resource in the same file with our component.
- */
-
- pascal ComponentResult
- CDGetCodecInfo(Handle storage,CodecInfo *info)
- {
- Globals **glob = (Globals **)storage;
-
- if ( info == nil )
- return(paramErr);
- BlockMove((Ptr)*((*glob)->sharedGlob)->info,(Ptr)info,sizeof(CodecInfo));
- return(noErr);
- }
-
-
- /************************************************************************************
- * When CDGetSimilarity is called, we return the percent of the compressed image A that
- * is different from compressed image B. This can be used by applications that use sequence
- * dynamics as an indicator for editing image sequences.
- *
- * If the codec cannot do a direct similarity comparison, the ICM decompresses image A and
- * do a comparison with image B. This call is provided so that a codec can save the time
- * of the intermediate decompress if it can do the comparison directly.
- */
-
- pascal ComponentResult
- CDGetSimilarity(Handle storage,PixMapHandle src,const Rect *srcRect,ImageDescriptionHandle desc,
- Ptr data,Fixed *similarity)
- {
- #pragma unused(storage,src,srcRect,desc,data,dif,refcon)
-
- /* This call is not implemented yet, which is okay, because its not used very much and is not mandatory */
-
- return(codecUnimpErr);
- }
-
-
- /************************************************************************************
- * When CDGetCompressedImageSize is called, we return the size in bytes of the given compressed
- * data ( for one image frame).
- */
-
- pascal ComponentResult
- CDGetCompressedImageSize(Handle storage,ImageDescriptionHandle desc,Ptr data,long dataSize,
- DataProcRecordPtr dataProc,long *size)
- {
- #pragma unused(storage,data,dataSize,dataProc)
-
-
- short width = (*desc)->width;
- short height = (*desc)->height;
- if ( size == nil )
- return(paramErr);
-
- /* we always end up with a fixed size. If we did not, we would return the worst case size */
-
- *size = ((width + (FONT_WIDTH-1))/FONT_WIDTH) * ((height+(FONT_HEIGHT-1))/FONT_HEIGHT);
- return(noErr);
- }
-
-
- /************************************************************************************
- * When CDGetMaxCompressionSize is called, we return the maximum size the compressed data for
- * the given image would be in bytes.
- */
-
- pascal ComponentResult
- CDGetMaxCompressionSize(Handle storage,PixMapHandle src,const Rect *srcRect,short depth,
- CodecQ quality,long *size)
- {
- #pragma unused(storage,src,depth,quality)
-
- short width = srcRect->right - srcRect->left;
- short height = srcRect->bottom - srcRect->top;
-
- /* we always end up with a fixed size. If we did not, we would return the worst case size */
-
- *size = 100 + ((width + (FONT_WIDTH-1))/FONT_WIDTH) * ((height+(FONT_HEIGHT-1))/FONT_HEIGHT);
-
- return(noErr);
- }
-
-
- /************************************************************************************
- * When CDGetCompressionTime is called, we return the approximate time for compressing
- * the given image would be in milliseconds. We also return the closest actual quality
- * we can handle for the requested value.
- */
-
- pascal ComponentResult
- CDGetCompressionTime(Handle storage,PixMapHandle src,const Rect *srcRect,short depth,
- CodecQ *spatialQuality,CodecQ *temporalQuality,unsigned long *time)
- {
- #pragma unused(storage,src,srcRect,depth)
-
- if (time)
- *time = 0; /* we don't know how many msecs */
-
- if ( spatialQuality ) {
- if ( *spatialQuality <= codecLowQuality ) {
- *spatialQuality = codecLowQuality;
- }
- else if ( *spatialQuality <= codecNormalQuality ) {
- *spatialQuality = codecNormalQuality;
- } else {
- *spatialQuality = codecHighQuality;
- }
- }
- if ( temporalQuality )
- *temporalQuality = 0;
- return(noErr);
- }
-
-
- /************************************************************************************
- * When CDTrimImage is called, we take the given compressed data and return only the portion
- * which is represented by the trimRect. We can return a little more if we have too, but we
- * need only return enough so that the image in trimRect is properly displayed. We then
- * adjust the rectangle to corresond to the same rectangle in the new trimmed data.
- */
-
- pascal ComponentResult
- CDTrimImage(Handle storage,ImageDescriptionHandle desc,Ptr inData,long inDataSize,
- DataProcRecordPtr dataProc,Ptr outData,long outDataSize,FlushProcRecordPtr flushProc,
- Rect *trimRect,ProgressProcRecordPtr progressProc)
- {
-
- return(codecUnimpErr);
-
- }
-